package com.zmn.oms.third.haobai.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.oms.business.interfaces.notifylog.OrderNotifyLogBService;
import com.zmn.oms.business.interfaces.third.HaobaiExtendOrderService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.notifylog.OrderNotifyLog;
import com.zmn.oms.model.entity.third.HaobaiExtendOrder;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.haobai.BuildSignUtil;
import com.zmn.oms.third.haobai.HaobaiApiInvoker;
import com.zmn.oms.third.haobai.HaobaiConsts;
import com.zmn.oms.third.haobai.dto.HaobaiResultDTO;
import com.zmn.oms.third.haobai.service.HaobaiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * @author: huangyifeng
 * @description: 号百接口实现
 * @create: 2020-03-10 14:31
 **/
@Slf4j
@Service("haobaiService")
public class HaobaiServiceImpl implements HaobaiService {

    @Autowired
    private OrderWorkService orderWorkService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private HaobaiExtendOrderService haobaiExtendOrderService;

    @Resource
    private OrderNotifyLogBService orderNotifyLogBService;

    @Override
    public void notifyOrderStatus(OrderWorkLogChange orderWorkLogChange) {
        this.saveSyncAmount(orderWorkLogChange, HaobaiConsts.STATUS_COMPLETE);
    }

    @Override
    public void syncOrderCancel(OrderWorkLogChange orderWorkLogChange) {
        this.saveSyncAmount(orderWorkLogChange, HaobaiConsts.STATUS_CANCEL);
    }

    @Override
    public String syncOrderStatus(Long orderId) throws OmsBaseException {
        OrderWork dbOrderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        if (dbOrderWork == null) {
            throw new OmsBaseException("订单不存在");
        }

        String orderStatus = null;
        Integer status = dbOrderWork.getStatus();
        Integer resultStatus = dbOrderWork.getResultStatus();
        if (Objects.equal(OrderStatusConsts.WORK_RESULT_FAIL, resultStatus)
                || Objects.equal(OrderStatusConsts.WORK_RESULT_DISCARD, resultStatus)) {
            orderStatus = HaobaiConsts.STATUS_CANCEL;
        }
        else if (Objects.equal(OrderStatusConsts.WORK_RESULT_SUCCESS, resultStatus)
                || status.intValue() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {
            orderStatus = HaobaiConsts.STATUS_COMPLETE;
        }

        if (orderStatus == null) {
            throw new OmsBaseException("不能确定订单状态！");
        }

        OrderWorkLogChange orderWorkLogChange = new OrderWorkLogChange();
        orderWorkLogChange.setOrderId(dbOrderWork.getOrderId());
        orderWorkLogChange.setMqMsgKey("null");
        orderWorkLogChange.setStatus(status);
        orderWorkLogChange.setResultStatus(resultStatus);
        orderWorkLogChange.setChannelId(dbOrderWork.getChannelId());

        HaobaiResultDTO haobaiResultDTO = this.saveSyncAmount(orderWorkLogChange, orderStatus);
        return haobaiResultDTO.getErrors();
    }

    // 保存同步金额
    private HaobaiResultDTO saveSyncAmount(OrderWorkLogChange orderWorkLogChange, String haobaiOrderState) {
        HaobaiResultDTO haobaiResultDTO = null;

        Long orderId = orderWorkLogChange.getOrderId();
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        boolean isHaobaiAPPOrder = Objects.equal(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_HAOBAI_APP);

        // 线下下单的订单，只同步特定地区的订单
        if (!isHaobaiAPPOrder && !HaobaiConsts.isNeedSyncOrder(orderWork.getCityId())) {
            log.info("[号百-便民平台] 订单不在有效城市，无需同步: orderId=[{}], cityId=[{}]", orderWork.getOrderId(),
                    orderWork.getCityId());

            haobaiResultDTO = new HaobaiResultDTO();
            haobaiResultDTO.setCode("0");
            haobaiResultDTO.setErrors("订单不在有效城市，无需同步");
            return haobaiResultDTO;
        }

        HaobaiExtendOrder haobaiExtendOrder = haobaiExtendOrderService.findByOrderId(orderId);
        if (haobaiExtendOrder == null) {
            haobaiExtendOrder = new HaobaiExtendOrder();
            haobaiExtendOrder.setCreater("sys");
            haobaiExtendOrder.setUpdater("sys");
            haobaiExtendOrder.setCreateTime(new Date());
            haobaiExtendOrder.setUpdateTime(haobaiExtendOrder.getCreateTime());

            haobaiExtendOrder.setOrderId(orderId);
            haobaiExtendOrder.setSyncTimes(0);
            haobaiExtendOrder.setOrderType(
                    HaobaiConsts.STATUS_COMPLETE.equals(haobaiOrderState) ? GlobalConsts.YES : GlobalConsts.NO);
            haobaiExtendOrder.setTotalAmount(calculateOrderAmount2Haobai(orderWork.getTotalAmount()));

            haobaiExtendOrderService.save(haobaiExtendOrder);
        }

        try {
            Integer channelOrderWayType =
                    isHaobaiAPPOrder ? HaobaiConsts.CHANNEL_ORDER_WAY_TWO : HaobaiConsts.CHANNEL_ORDER_WAY_FIVE;
            Map<String, Object> params = paramsTransformation(orderWork, haobaiOrderState, channelOrderWayType,
                    haobaiExtendOrder.getTotalAmount());
            haobaiResultDTO = HaobaiApiInvoker.sendingNotice(params);

            if ("0".equals(haobaiResultDTO.getCode())) {
                // TODO -lhl 更新 haobaiExtendOrder
            }
            else {
                log.info("[号百-便民平台] 同步{}订单失败：[{}]",
                        HaobaiConsts.getStatusName(haobaiOrderState), haobaiResultDTO.getErrors());
            }

            saveSyncResult(orderWorkLogChange, haobaiOrderState, haobaiResultDTO);
        } catch (OmsBaseException e) {
            log.error(String.format("[号百-便民平台] 同步%s订单异常：%s",
                    HaobaiConsts.getStatusName(haobaiOrderState), e.getMessage()), e);

            if (haobaiResultDTO == null) {
                haobaiResultDTO = new HaobaiResultDTO();
                haobaiResultDTO.setCode("1");
                haobaiResultDTO.setErrors(String.format("同步失败：%s", e.getMessage()));
            }
        }

        return haobaiResultDTO;
    }

    // 请求参数
    private Map<String, Object> paramsTransformation(OrderWork orderWork,
                                                     String haobaiOrderState,
                                                     Integer channelOrderWayType,
                                                     Integer totalMoney)
            throws OmsBaseException {

        Long orderId = orderWork.getOrderId();
        boolean isComplete = HaobaiConsts.STATUS_COMPLETE.equals(haobaiOrderState);
        boolean isCancel = HaobaiConsts.STATUS_CANCEL.equals(haobaiOrderState);

        String applianceCode = HaobaiConsts.APPLIANCE_REPAIR_CODE;
        String applianceName = HaobaiConsts.APPLIANCE_REPAIR_NAME;
        if (Objects.equal(GlobalConsts.SERV_CATEG_CLEAN, orderWork.getServCategId())) {
            applianceCode = HaobaiConsts.APPLIANCE_CLEAN_CODE;
            applianceName = HaobaiConsts.APPLIANCE_CLEAN_NAME;
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());

        Map<String, Object> params = Maps.newHashMap();
        params.put("customerName", orderDetail.getUserName());
        params.put("phoneNo", orderDetail.getTelephone());
        params.put("orderNo", String.valueOf(orderId));

        params.put("orderWay", channelOrderWayType);
        params.put("orderTime", DateUtil.toString(orderDetail.getCreateTime(), DateUtil.FORMAT_DATETIME2));
        params.put("commodityCode", applianceCode);
        params.put("areaCode", orderDetail.getCountyId());
        params.put("status", haobaiOrderState);

        try {
            String sign = BuildSignUtil.sign(params, HaobaiConsts.HAOBAI_SERECT);
            params.put("sign", sign);
        } catch (Exception e) {
            log.error(String.format("[号百-便民平台] 加密失败: %s, params=[%s]", e.getMessage(), JSON.toJSONString(params)), e);
            throw new OmsBaseException("[号百-便民平台] 加密失败！", e);
        }

        params.put("commodityName", applianceName);
        params.put("needInvoice", 1);
        params.put("provinceCode", orderDetail.getProvinceId());
        params.put("provinceName", orderDetail.getProvinceName());
        params.put("cityCode", orderWork.getCityId());
        params.put("cityName", orderDetail.getCityName());
        params.put("areaName", orderDetail.getCountyName());
        params.put("addressDesc", orderDetail.getAddress());
        params.put("completeTime", DateUtil.getNowFormatted(DateUtil.FORMAT_DATETIME2));
        params.put("productCode", HaobaiConsts.getProductCode(
                orderWork.getProductId(), orderWork.getCategOneId(), orderWork.getServCategId()
        ));

        boolean isEffectivityOrder = HaobaiConsts.isEffectivityOrder(orderWork.getCityId());
        params.put("effectivity", isEffectivityOrder ? HaobaiConsts.ORDER_EFFECTIVE : HaobaiConsts.ORDER_INVALID);

        Map<String, Object> detail = Maps.newHashMap();
        Map<String, Object>  partnerDetail = Maps.newHashMap();
        // 无效订单
        if (isCancel) {
            params.put("originalPrice", "0");
            params.put("amount", "0");
            detail.put("unitPrice", "0");
            detail.put("price", "0");
            partnerDetail.put("partnerType", "0");
        }
        // 有效订单
        else if (isComplete) {
            params.put("originalPrice", totalMoney);
            params.put("amount", totalMoney);
            detail.put("unitPrice", totalMoney);
            detail.put("price", totalMoney);
            partnerDetail.put("partnerType", totalMoney);
        }
        else {
            log.error("[号百-便民平台] 无法识别给定的号百订单状态：orderId=[{}], haobaiOrderState=[{}]",
                    orderId, haobaiOrderState);
            throw new OmsBaseException(String.format("无法识别给定的号百订单状态：haobaiOrderState=[%s]", haobaiOrderState));
        }

        detail.put("itemCode", applianceCode);
        detail.put("itemName", applianceName);
        detail.put("quantity", 1);
        detail.put("status", 2);    // 1:新建  2:完成
        params.put("orderDetail", detail);

        partnerDetail.put("partnerOrgCode", HaobaiConsts.ZMN_ORGANIZATION_CODE);
        partnerDetail.put("contractCode", HaobaiConsts.HAOBAI_CONTRACT_CODE);
        params.put("partnerDetail", partnerDetail);

        return params;
    }

    /**
     * 线下渠道的订单，同步给号百的金额需做处理，规则如下：
     *  100元以内（含）：取原值；
     *  100~320元（含）：取原值的一半，并取整；
     *  320元以上：在100~200元之间取随机值
     * @param orderAmount 原始订单金额，单位：分
     * @return
     */
    private int calculateOrderAmount2Haobai(Integer orderAmount) {
        int orderAmount2Haobai = Optional.ofNullable(orderAmount).orElse(0);
        // 100元以内（含）：取原值；
        if (orderAmount2Haobai <= 10000) {
            return orderAmount2Haobai;
        }
        // 100~320元（含）：取原值的一半，并取整；
        if (orderAmount2Haobai <= 32000) {

            return (orderAmount2Haobai/200)*100;
        }
        // 320元以上：在100~200元之间取随机值
        return (new BigDecimal(Math.random() * 100).intValue() + 100) * 100;
    }

    /**
     * 保存状态同步结果信息
     * @param orderWorkLogChange
     * @param statusCode
     * @param result
     */
    private void saveSyncResult(OrderWorkLogChange orderWorkLogChange, String statusCode, HaobaiResultDTO result) {
        if (result == null) {
            return;
        }

        boolean isSuccess = "0".equals(result.getCode());

        OrderNotifyLog orderNotifyLog = new OrderNotifyLog();
        orderNotifyLog.setMqMsgKey(orderWorkLogChange.getMqMsgKey());
        orderNotifyLog.setOrderId(orderWorkLogChange.getOrderId());
        orderNotifyLog.setChannelId(orderWorkLogChange.getChannelId());
        orderNotifyLog.setOrderStatus(orderWorkLogChange.getStatus());
        orderNotifyLog.setOrderResultStatus(orderWorkLogChange.getResultStatus());
        orderNotifyLog.setNotifyStatus(statusCode);
        orderNotifyLog.setType(OrderConsts.ORDER_NOTIFY_TYPE_CHANGE);
        orderNotifyLog.setNotifyTime(DateUtil.getNow());
        orderNotifyLog.setNotifyResultMsg(String.format("[推送%s订单]-%s", HaobaiConsts.getStatusName(statusCode),
                        isSuccess ? "成功" : result.getErrors() ));

        ResultDTO resultDTO = new ResultDTO();
        resultDTO.setStatus(isSuccess ? 200 : 100);
        resultDTO.setData(orderNotifyLog);

        orderNotifyLogBService.saveNotifyLog(resultDTO);
    }

}
